package org.dhbw.jee.persistence.dataAccess;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

public class DataAccessObject implements IDataAccessObject, Serializable {
	private static final long serialVersionUID = 1L;

	@PersistenceContext
	private EntityManager entityManager;

	public DataAccessObject() {
		//
	}

	@Override
	public <T, R> T getSingle(Class<T> type, R primaryKey) {

		String primaryKeyProperty = null;

		for (Field f : type.getDeclaredFields())
			if (f.isAnnotationPresent(Id.class)) {
				primaryKeyProperty = f.getName();
				break;
			}

		if (primaryKeyProperty == null) {
			System.out.println("no @Id found in Class: " + type);
			return null;
		}

		CriteriaBuilder builder = entityManager.getCriteriaBuilder();
		CriteriaQuery<T> query = builder.createQuery(type);
		Root<T> fromRoot = query.from(type);
		query.where(builder.equal(fromRoot.get(primaryKeyProperty), primaryKey));
		return entityManager.createQuery(query).getSingleResult();
	}

	@Override
	public <T> T getSingleByQuery(Class<T> type, String query, Object... params) {
		TypedQuery<T> typedQuery = entityManager.createNamedQuery(query, type);
		for (int i = 0; i < params.length; i++)
			typedQuery.setParameter(i + 1, params[i]);
		return typedQuery.getSingleResult();
	}

	@Override
	public <T> List<T> getAll(Class<T> type) {
		CriteriaQuery<T> query = entityManager.getCriteriaBuilder().createQuery(type);
		return entityManager.createQuery(query).getResultList();
	}

	@Override
	public <T> List<T> getAllByQuery(Class<T> type, String query, Object... params) {
		TypedQuery<T> typedQuery = entityManager.createNamedQuery(query, type);
		for (int i = 0; i < params.length; i++)
			typedQuery.setParameter(i + 1, params[i]);
		return typedQuery.getResultList();
	}

	@Override
	public <T> boolean persist(T object) {
		return false;
	}

	@Override
	public <T> boolean delete(T object) {
		return false;
	}

	@Override
	public <T> boolean update(T object) {
		return false;
	}

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

}
